iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 5
0
Mobile Development

傻瓜也要能看懂的Flutter學習心得系列 第 5

[Day 5]終於要開始寫程式了......嗎?

  • 分享至 

  • xImage
  •  

昨天講到「使用IDE提供的標準功能去新增一個Flutter」,這個專案打開後,IDE介面大概長這樣...

https://ithelp.ithome.com.tw/upload/images/20200920/20130496NwBF6TL1k0.png

跟昨天介紹的圖片相比,同樣都有「專案管理區」(左邊)和「程式碼編輯區」(右邊),不同的地方主要應該在整個介面的下半部多了「Run/Console」。(下圖將這整個區塊放大後拉出來給各位看。)

https://ithelp.ithome.com.tw/upload/images/20200920/20130496zaZeYzHfTP.png

「Run/Console」的目的在於讓開發者知道「編譯器」運作的情況,像編譯是否成功?引入其他專案是否成功?.......如果失敗,原因為何?

除了這個功能以外,這個區塊還有幾個功能可以給開發者使用,但我個人覺得目前為止需要特別介紹的有Logcat和Terminal。

Logcat是SDK的特殊功能。目的是連結Android裝置(不管是真實裝置或虛擬裝置),接收Android裝置傳回的底層訊息。邏輯上來說,Logcat是個獨立在IDE之外、附屬在SDK內的功能,它的運作正常與否並非由IDE來監督和保障,IDE只是經由「ADT」工具的設定,讓它知道去接收Logcat傳出的訊息而已。

講白話文一點來說,這個Logcat就像個廣播電台,而任何被ADT設定過的程式都會變成收音機。

要如何監聽Logcat的訊息?或Logcat如何知道要把訊息傳給誰?

概念上來說,電腦最初設定只是個由CPU(和電源)構成的金屬盒子而已,處理完任何資訊,要不是儲存進主記憶體中,不然就是指定要往哪個「Port」傳輸結果,比如電腦有1~10個Port,Port:1是喇叭,往Port:1傳輸的資料都會送向喇叭,Port:2是螢幕,如果把本來要送往喇叭的資料往這個地方傳輸,螢幕就會像得了羊癲瘋一樣失控呈現各種無意義的影像。(除非你剛好把本來要送往螢幕的的資料設定為要送給了喇吧,但實際執行時卻把喇吧誤認為螢幕。雖然結果正確,但實際上已經連續發生兩次錯誤。)

就連WWW全球網際網路也有一個專用的Port:8888。

早期的電腦,各個Port能夠做的事情通常都有強制性,後來開始有一些多功能、甚至萬用的Port誕生,例如IDE(硬碟介面)、PCI、和USB。

另外還有一種「沒有實質對外」的Port,這種Port可以用來作為內部的系統溝通用。比如:軟體A可以監聽Port:X接收到的資料。這裡的軟體A可能就是IDE,而往Port:X傳輸資料的就是Logcat。

舉一反三一下:所謂的終端機模式說白了也是個「監聽Port:Y」的軟體罷了!它本身並不具備任何作業系統的實際功能。所以我們也可以在IDE中看到「Terminal:終端機」這個東西。

以上講這麼多,是想表示:功能A往Port:Z傳輸資料,凡是監聽Port:Z的功能都可以用來回應、輔助、甚至管理功能A,懂得使用Port,就可以開發出很多標準教材中不會介紹的功能。(但這是條很辛苦的路,而且到最後會發現與其自己利用這些機制去設計些獨特的功能,直接使用別人設計好、也經過充分測試的東西比較快,所以這條路相形之下「一無所獲」的風險很高。)

以上,在開始寫程式以前需要知道的SDK和IDE的知識都簡單介紹過了,就開始寫第一支程式吧!

找到「Start a new Flutter project」然後點下去.......

第一頁是要我們選擇專案的類型......先選擇Application,然後到下一頁。

設定專案的名稱、SDK路徑(昨天安裝Flutter SDK的地方)、專案存檔位置...這些都好懂。

第三頁,「Package Name」...這東西的格式有點像網址URL,它的目的有點像是作為一個專案的「身分證」,同時也是專案架構的大綱,以此讓大家可以知道它的獨一無二性。像Flutter,任何軟體都可以取名叫Flutter,也可以在系統中以Flutter的名稱被安裝起來,但專案的架構不會騙人,比如正牌的Flutter專案名稱可能是「com.google.flutter」,但冒牌的Flutter專案名稱可能「tw.hsu.flutter」。

而且不管是未來要在Google Play或Apple Market上發行,專案名稱絕對不能跟其他專案相同,系統會拒絕讓開發者建立APP項目。

所以幫自己的Project取的獨特的PackageName是很重要的事情。

取好名字後就可以按下「結束」,IDE就會幫你建立一個最基本的專案。

這個專案會附上一段名為「main.dart」的基本程式碼......

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headline4,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}

這個程式碼會建構一支APP,裏頭有個簡單的標題「Flutter Demo Home Page」在UI最上方,兩行Text在畫面正中央,上方Text顯示「You have pushed the button this many times」,下方Text顯示「0」,右下角有個圓形的按鈕(按下這個按鈕,下方Text內的數字會變化)。(其實大家都可以在程式碼中找到這些字。試著修改看看。)

在IDE介面上找到下面這塊工具,可以看到一個綠色的三角形,那是「執行測試」的功能,

https://ithelp.ithome.com.tw/upload/images/20200920/20130496HTJPS5BxHP.png

接上手機後,(如果手機有啟動開發者模式,)IDE會偵測到手機的存在並顯示在介面上。(我用的測試手機是Samsung的A50。)

https://ithelp.ithome.com.tw/upload/images/20200920/20130496wmoqkvJ6PT.png

(第一次啟動測試會需要比較久時間,如果是在Windows上,那需要無比耐心。)

這支基本程式的程式碼,看過去會讓人覺得好多好複雜...

但有些秘訣可以方便大家快速進入:任何程式碼都有個「起始點」或「進入點」,它的邏輯會隨著程式語言的不同、還有運行的平台不同而有差,但嚴格說起來,「同一種程式語言,它的邏輯是差不多的。」

以Flutter來說,APP啟動後第一件事情是執行main函數。

void main() {
  runApp(MyApp());
}

但什麼是函數?

最早的程式結構與功能很簡單,不管是什麼樣的功能,從「只是輸出一行訊息到螢幕上」到「讓使用者輸入兩組數字,將它們相加後輸出結果」,設計上就是「讓程式從第一行程式碼開始執行、執行到最後一行結束。」

但隨著功能越來越複雜,開始出現像「第一次運算完後的結果若為A類,則接著執行A功能,如果結果為B類,則接著執行B功能,如果結果為C類.........」如果將A功能、B功能、C功能...的程式碼都寫在「第一次運算完後判斷結果為A類、B類、C類...」的判斷功能內,那這個判斷功能會變得很複雜、很難閱讀。

所以乾脆把要做的功能程式碼從判斷功能內拉出來,寫在程式碼內完全不相干的區段,然後給這個區段做個記號並取個名字,「從這個地方開始、到那個地方結束,這一段程式碼是個獨立的功能,可以在別的程式碼內使用它的名字來執行它。」這就是函數。

以上面那段程式碼來說,「main」就是這個函數的名稱,後面固定要加個「()」,而後面的「{」和「}」之間的程式碼就是開發者設計的功能。

同樣的道理,「runApp()」也是個函數,但後面沒有「{」和「}」,因為這是在「使用」這個函數。(這個函數是由「其他專案」所定義好的,不需要加上「{」和「}」是因為它的內容是寫在「其他專案」內。我們的程式引用了「其他專案」後就有使用這個函數的能力。)

函數還有很多種意義,像最初的程式語言要進行開發,開發者必須要記好程式碼的行數,例如這段功能從第100行開始、第110行結束,如果第10行的程式碼判斷完要執行它,就要下指令「goto 100:我接下來跳到第100行去執行那裡的功能」。

但這種使用「goto...」的程式語言很難維護,因為隨著程式碼擴充,本來功能是從第100行開始、第110行結束,後來卻變成從110行開始、120行結束,但使用功能的地方,在程式碼上卻還寫著「到第100行」這樣的指令,這時候就會導致程式執行錯誤、甚至根本無法執行而Crash。(所以今天絕大多數的高階程式語言都已經直接拿掉「goto」這種功能了。)

但以Flutter來說,函數讓程式碼的框架跳脫了「不是從第一行開始執行起」。

main函數基本上可以寫在任何順序,例如你可以在main之前寫一個main2函數。

void main2() {
  runApp(MyApp());
}

void main() {
  runApp(MyApp());
}

但依然會保證它從main開始執行。


上一篇
[Day 4] 要開始動手寫程式了嗎?
下一篇
[Day 6]main、runApp、和Widget
系列文
傻瓜也要能看懂的Flutter學習心得10
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言